// Learn TypeScript:
//  - https://docs.cocos.com/creator/manual/en/scripting/typescript.html
// Learn Attribute:
//  - https://docs.cocos.com/creator/manual/en/scripting/reference/attributes.html
// Learn life-cycle callbacks:
//  - https://docs.cocos.com/creator/manual/en/scripting/life-cycle-callbacks.html

import { UNetMgr } from "./UNetMgr";

export class StepData {
    frame:number;
    cmds:Array<any>;
    sync:{p:cc.Vec3,a:number,s:cc.Vec3};
    data:any
}

const {ccclass, property,disallowMultiple} = cc._decorator;

@ccclass
@disallowMultiple
export default class UNetIdentity extends cc.Component {
    _uuid:string;

    /** 是否是本人 */
    isLocalPlayer : boolean = false;

    userData : any = {}

    private _updatedata : any = {};
    private _cmdcontrol : Array<any> = [];
    private lastSaveDataTime : number = 2;

    private lockStepTween : cc.Tween = null;
    private _isonloadcall = false;

    onLoad(){
        this._isonloadcall = true;
        this.node.on(cc.Node.EventType.POSITION_CHANGED,this._onChangePos,this)
        this.node.on(cc.Node.EventType.ROTATION_CHANGED,this._onChangeAngle,this)
        this.node.on(cc.Node.EventType.SCALE_CHANGED,this._onChangeScale,this)
    }

    private _onChangePos(){
        if(UNetMgr.model === UNetMgr.SyncModel.SelfNoDelay){
            this._updatedata.p = cc.v3(Math.floor(this.node.x),Math.floor(this.node.y),Math.floor(this.node.z))
        }
    }
    private _onChangeAngle(){
        this._updatedata.a = this.node.angle
    }
    private _onChangeScale(){
        this._updatedata.s = cc.v3(Math.floor(this.node.scaleX),Math.floor(this.node.scaleY),Math.floor(this.node.scaleZ))
    }

    protected SendCMD(obj){
        this._cmdcontrol.push(obj)
    }
    
    /** 主角初始化 */
    OnSelfPlayerInit(){

    }

    /** 人物头像、名字等属性初始化 */
    OnSyncUserEnter(data){
        // console.log('OnSyncUserInfo:',data);
    }
    /** 用户退出房间 返回true时框架自动销毁 */
    OnSyncUserExit(data):boolean{
        cc.log('用户退出房间:',data);
        return true;
    }
    /** 其他用户重新连接激活 */
    OnSyncUserReActive(){

    }

    /** 首次或重连时同步场景数据 */
    OnSyncSceneData(data:any){
        data.p && this.node.setPosition(data.p.x || 0,data.p.y || 0,data.p.z || 0)
        data.a && (this.node.angle = data.a || 0)
        data.s && this.node.setScale(data.s.x || 0, data.s.y || 0,data.s.z || 0)
    }

    /** 帧同步主要函数 */
    OnFrameUpdate(data:any){
        if(this.isLocalPlayer){
            return
        }
        if(data.sync){
            var tween = {};
            data.sync.p && (tween = {x:data.sync.p.x,y:data.sync.p.y,z:data.sync.p.z})
            data.sync.a && (tween['angle'] = data.sync.a)
            data.sync.s && (tween = {x:data.sync.s.x,y:data.sync.s.y,z:data.sync.s.z})
            if(Object.keys(tween).length > 0){
                this.lockStepTween && this.lockStepTween.stop();
                this.lockStepTween = cc.tween(this.node).to(UNetMgr.delay+0.02,tween).call(()=>{
                    this.lockStepTween = null
                }).start();
            }
            console.log('OnFrameUpdate:',UNetMgr.room.frame)
        }
        // cc.tween(this.node).to({x:})
    }

    /** 同步自身其他数据，比如武器id */
    OnGetSyncUserData():any{

    }


    // 同步场景中的用户数据
    private _saveSceneUser(){
        this._onChangePos()
        this._onChangeAngle()
        this._onChangeScale()
        this._updatedata.d = this.OnGetSyncUserData() || {}
        UNetMgr.SendRoomMsg('suser',this._updatedata);
        this._updatedata = {}
    }

    public getOfflineStatus(){
        var a :any = {}
        a.p = cc.v3(Math.floor(this.node.x),Math.floor(this.node.y),Math.floor(this.node.z))
        a.a = this.node.angle
        a.s = cc.v3(Math.floor(this.node.scaleX),Math.floor(this.node.scaleY),Math.floor(this.node.scaleZ))
        a.d = this.OnGetSyncUserData()
        return a;
    }

    /** 帧同步更新 */
    updateLockStep(dt:number){
        if(!this._isonloadcall){
            cc.error('未执行onload函数')
            return
        }
        if(!this.isLocalPlayer){
            return
        }
        var v = {
            frame:UNetMgr.room.frame+1,
            cmds:null,
            sync:null
        }
        if(this._cmdcontrol.length > 0){
            v.cmds = this._cmdcontrol
            this._cmdcontrol = []
        } 
        if(Object.keys(this._updatedata).length > 0){
            v.sync = this._updatedata
            this._updatedata = {}
        }

        if(v.cmds || v.sync){
            UNetMgr.SendRoomMsg('frame',v);
        }
        // (v.cmds || v.sync || v.data) && UNetMgr.SendRoomMsg('frame',v);

        if(this.lastSaveDataTime <= 0){
            this._saveSceneUser()
            this.lastSaveDataTime = 1
        } else {
            this.lastSaveDataTime -= dt;
        }
    }

    lateUpdate(dt:number){
        this.updateLockStep(dt)
    }
}
